#include "CViewD3D9.h"
#include "SRendererDX9.h"

#include "CImage.h"

#define DX9_CUSTOM_VERTEX_FORMAT D3DFVF_XYZ | D3DFVF_TEX0

// http://ccollomb.free.fr/blog/?p=50

//----------------------------------------------
CViewD3D9::CViewD3D9(HWND hWnd, CViewDesc& oDesc) :
CView(hWnd, oDesc),
m_pD3dDevice(NULL),
m_iWidth(oDesc.width),
m_iHeight(oDesc.height),
m_pDXQuad(NULL)
{
}

//----------------------------------------------
CViewD3D9::~CViewD3D9()
{
	if (m_pD3dDevice != NULL)
		m_pD3dDevice->Release();
}

//----------------------------------------------
void CViewD3D9::init()
{
	D3DPRESENT_PARAMETERS oD3dpp;

	ZeroMemory(&oD3dpp, sizeof(oD3dpp));
	oD3dpp.Windowed				= FALSE;
	oD3dpp.SwapEffect			= D3DSWAPEFFECT_DISCARD;
	oD3dpp.hDeviceWindow		= m_hWnd;
	oD3dpp.BackBufferFormat		= D3DFMT_X8R8G8B8;
	oD3dpp.BackBufferWidth		= m_iWidth;
	oD3dpp.BackBufferHeight		= m_iHeight;
	oD3dpp.PresentationInterval	= D3DPRESENT_INTERVAL_ONE;
	oD3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
	oD3dpp.EnableAutoDepthStencil = FALSE;

	SRendererDX9::instance()->m_pD3d->CreateDevice(
		D3DADAPTER_DEFAULT,
		D3DDEVTYPE_HAL,
		m_hWnd,
		D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_ADAPTERGROUP_DEVICE,
		&oD3dpp,
		&m_pD3dDevice);

	m_pD3dDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR );
	m_pD3dDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR );
	m_pD3dDevice->SetSamplerState( 0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR );

	m_pD3dDevice->SetRenderState(D3DRS_AMBIENT, RGB(255,255,255));
	m_pD3dDevice->SetRenderState(D3DRS_LIGHTING, false);
	m_pD3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
	m_pD3dDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
	m_pD3dDevice->SetFVF(DX9_CUSTOM_VERTEX_FORMAT); //set vertex format (NEW)
}

//----------------------------------------------
void CViewD3D9::createQuad()
{
	m_pD3dDevice->CreateVertexBuffer(sizeof(g_tQuad),
		D3DUSAGE_WRITEONLY,
		DX9_CUSTOM_VERTEX_FORMAT,
		D3DPOOL_MANAGED,
		&m_pDXQuad,
		NULL);

	VOID* pData;

	m_pDXQuad->Lock(0, sizeof(pData), (void**)&pData,0);
	memcpy(pData, g_tQuad, sizeof(g_tQuad));
	m_pDXQuad->Unlock();
}

//----------------------------------------------
void CViewD3D9::render()
{
	m_pD3dDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 40, 100), 1.0f, 0);
	m_pD3dDevice->BeginScene();

	// Draw quad
	m_pD3dDevice->SetStreamSource(0, m_pDXQuad, 0, sizeof(CVertex));
	m_pD3dDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);

	m_pD3dDevice->EndScene();
	/*m_pD3dDevice->GetSwapChain( 0, &pSwapChain ); 
	pSwapChain->Present( NULL, NULL, NULL, NULL, 0 );*/

	//pSwapChain->GetBackBuffer, 
	//pD3DDevice->StretchRect( pBackBuffer, NULL, pBackBufferAdapter, NULL, D3DTEXF_NONE );
	//pSwapChainAdapter->Present( NULL, NULL, NULL, NULL, 0 );
	m_pD3dDevice->Present(NULL, NULL, NULL, NULL);
}

//----------------------------------------------
bool CViewD3D9::loadTexture(CImage& oImage)
{
	HRESULT hRes;
	LPDIRECT3DTEXTURE9 pTexture;
	hRes = m_pD3dDevice->CreateTexture(oImage.getWidth(),
		oImage.getHeight(),
		1,
		0,
		D3DFMT_R8G8B8,
		D3DPOOL_DEFAULT,
		&pTexture,
		NULL
		);
	if (FAILED(hRes)) return false;
	D3DLOCKED_RECT oLockedRect;
	hRes = pTexture->LockRect(0, &oLockedRect, 0, D3DLOCK_DISCARD);
	if (FAILED(hRes))
	{
		pTexture->Release();
		return false;
	}
	unsigned char* pSrcPix = oImage.getBuffer();
	unsigned char* pDstPix = static_cast<unsigned char*>( oLockedRect.pBits );
	for (int y = 0; y < oImage.getHeight(); y++)
	{
		memcpy(pDstPix, pSrcPix, oImage.getWidth() * sizeof(unsigned char) * 3);
		//std::copy (pSrcPix, pSrcPix + oImage.m_iWidth * sizeof(unsigned char) * 3, pDstPix);
		pSrcPix += oImage.getWidth() * sizeof(unsigned char) * 3;
		pDstPix += oLockedRect.Pitch;
	}
	hRes = pTexture->UnlockRect(0);

	if (FAILED(hRes))
	{
		pTexture->Release();
		return false;
	}
	else
	{
		m_pDXTextureMap[&oImage] = pTexture;
		//oImage.m_pDeviceData = pTexture;
		return true;
	}
}

//----------------------------------------------
void CViewD3D9::unloadTexture(CImage& oImage)
{
	//LPDIRECT3DTEXTURE9 pTexture = static_cast<LPDIRECT3DTEXTURE9>(oImage.m_pDeviceData);
	if (m_pDXTextureMap.find(&oImage) != m_pDXTextureMap.end())
	{
		LPDIRECT3DTEXTURE9 pTexture = m_pDXTextureMap[&oImage];
		pTexture->Release();
		//oImage.m_pDeviceData = NULL;
	}
}
